import java.util.concurrent.CompletableFuture;

/**
 * 描述:线程部分
 *
 * 1.如何理解多线程？
 *      1.比如电脑上可以允许多个程序，每个程序是一个进程，每个进程都可以开辟出多个线程去执行不同的业务
 *      2.多线程可以提高系统业务执行的效率，比如我处理一个2000行的excel表格，我用一个线程处理，需要花10s，我用5个线程每个线程处理400行只要2s
 *      3.一般java中开启多线程的方式是：继承Thread，实现runnable，实现callable，callable有返回值允许抛出异常，另外两个没有
 *      4.但是在工作中我一般不用这些方式直接使用多线程，一般采用线程池：一是因为开辟线程是一个耗时的操作，利用池化思想在一开始就开辟了几个线程，
 *        然后线程用完不销毁，而是等待在那到有新的任务进来继续执行，提高效率并且便于管理线程
 *      5.创建线程池的方式是：new ThreadPoolExecutor()，里面传递核心线程数，最大线程数，超时时间，超时时间单位，任务队列和拒绝策略这些参数，
 *        一般这么创建是做全局线程池配置的，平时方便会直接使用Executors创建，可以创建四种类型的线程池
 *              1.newFixedThreadPool：创建定长线程池
 *              2.newCachedThreadPool：创建可缓存的线程池，线程数量不定，超过60s空间的话闲置线程就会被回收，适合执行大量的耗时较少的任务
 *              3.newScheduledThreadPool：延时允许或者定期允许的线程池，适合执行周期性重复的任务
 *              4.newSingleThreadPool：创建单线程的线程池
 *      6.一般线程池的应用在处理批量任务上，同时调用好多个复杂接口，配合countDownLatch使用
 * 2.线程池的拒绝策略
 *      1.AbortPolicy：默认拒绝策略，丢弃任务并且抛出异常，后面的请求和任务进来都会抛出异常
 *      2.DiscardPolicy：丢弃任务，但不抛出异常，后续提交的任务也会之间丢弃
 *      3.丢弃队列最前面的任务，然后重新提交被丢弃的任务
 *      4.由调用线程执行该任务
 *
 * 3.线程数量的设置
 *      1.CPU密集型
 *          1.CPU密集型的意思就是该任务需要大量运算，而没有阻塞，CPU一直全速运行
 *          2.CPU密集型任务只有在真正的多核CPU上才可能得到加速（通过多线程）
 *          3. CPU密集型任务配置尽可能少的线程数
 *          4.CPU密集型线程数配置公式：(CPU核数+1)个线程的线程池
 *      2.IO密集型
 *          1.IO密集型，即该任务需要大量的IO，即大量的阻塞
 *          2.IO密集型任务中使用多线程可以大大的加速程序运行，即使在单核CPU上，这种加速主要利用了被浪费掉的阻塞时间
 *          3.由于IO密集型任务线程并不是一直在执行任务，则应配置尽可能多的线程  CPU核数 * 2
 *          4.CPU核数 / (1 – 阻塞系数)（0.8~0.9之间）  8核 / (1 – 0.9) = 80个线程数
 *
 * 4.Future和CompletableFuture的区别
 *      1.Future是开启多线程后，可以对callable的返回值进行获取，用get方法，但是会阻塞在主线程中，并不是真正的异步。
 *      2.而CompletableFuture是真正的异步，它通过回调的方式获取数据，并且可以进行任务编排，实现异步任务的先后顺序。
 *        异步任务结束后，需要用其结果继续操作的时候，无需等待
 *
 *
 * @author Youjm
 * @created 2022/2/24 20:44
 */
public class ThreadS {

    public static void main(String[] args) {

        String result = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hi Boy";
        }).applyToEither(CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hi Girl";
        }),(s)->{return s;}).join();
        System.out.println(result);

    }

}
